package statemachine;

import com.alibaba.cola.statemachine.Action;
import com.alibaba.cola.statemachine.Condition;
import com.alibaba.cola.statemachine.StateMachine;
import com.alibaba.cola.statemachine.builder.StateMachineBuilder;
import com.alibaba.cola.statemachine.builder.StateMachineBuilderFactory;
import lombok.Data;

import static org.junit.Assert.assertEquals;

/**
 * @Author zhangtao
 * @create 2023/8/9 15:47
 */

public class ColaStatemachine {
    // 订单状态（States)
    enum OrderState {
        INIT,
        PAID,
        DELIVERED,
        REFUNDED;
    }

    // 订单事件（Events）
    enum OrderEvent {
        PAY_SUCCESS,
        PAY_FAIL,
        DELIVERED_SUCCESS,
        REFUND_SUCCESS;
    }

    // 订单（Context)
    @Data
    static class Order {
        String operator = "frank";
        String orderId = "123465";
        boolean sucess;
    }

    static String MACHINE_ID = "orderStateMachine";

    public void testInternalNormal() {
        StateMachineBuilder<OrderState, OrderEvent, Order> builder = StateMachineBuilderFactory.create();

        builder.internalTransition()
                .within(OrderState.PAID)
                .on(OrderEvent.DELIVERED_SUCCESS)
                .when(checkCondition())
                .perform(doAction());

        StateMachine<OrderState, OrderEvent, Order> stateMachine = builder.build(MACHINE_ID + "1");

        OrderState target = stateMachine.fireEvent(OrderState.PAID, OrderEvent.DELIVERED_SUCCESS, new Order());
        assertEquals(OrderState.PAID, target);
    }

    public void testExternalTransitionsNormal() {
        StateMachineBuilder<OrderState, OrderEvent, Order> builder = StateMachineBuilderFactory.create();

        builder.externalTransitions()
                .fromAmong(OrderState.PAID, OrderState.DELIVERED)
                .to(OrderState.REFUNDED)
                .on(OrderEvent.REFUND_SUCCESS)
                .when(checkCondition())
                .perform(doAction());

        StateMachine<OrderState, OrderEvent, Order> stateMachine = builder.build(MACHINE_ID + "2");

        OrderState target = stateMachine.fireEvent(OrderState.PAID, OrderEvent.REFUND_SUCCESS, new Order());
        assertEquals(OrderState.REFUNDED, target);

        Order order1 = new Order();
        stateMachine.fireEvent(OrderState.DELIVERED, OrderEvent.REFUND_SUCCESS, order1);
        Order order = new Order();
        stateMachine.fireEvent(OrderState.INIT, OrderEvent.REFUND_SUCCESS, order);
        if (order1.sucess) {
            System.out.println("执行成功");
        } else {
            System.out.println("执行失败");
        }
    }

    private Condition<Order> checkCondition() {
        return order -> {
            System.out.println("Check condition : " + order);
            return true;
        };
    }

    private Action<OrderState, OrderEvent, Order> doAction() {
        return (from, to, event, ctx) -> {
            ctx.sucess = true;
            System.out.println(
                    ctx.operator + " is operating " + ctx.orderId + " from:" + from + " to:" + to + " on:" + event);

        };
    }

    public static void main(String[] args) {
        ColaStatemachine statemachine = new ColaStatemachine();
        statemachine.testExternalTransitionsNormal();
    }


}
